package com.vict.framework.pay.aspect;

import com.vict.framework.FrameworkCommon;
import com.vict.framework.pay.bean.PayArgsDto;
import com.vict.framework.pay.bean.PayAwaitDTO;
import com.vict.framework.pay.bean.PayInnerDto;
import com.vict.framework.pay.service.FramworkPayInnerService;
import com.vict.framework.utils.UserContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;

@Slf4j
@Aspect
@Component
public class PayAwaitAspect {

    @Autowired
    private FramworkPayInnerService framworkPayInnerService;

    @Around("@annotation(com.vict.framework.pay.annotation.PayAwait)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        try{
            Object[] args = joinPoint.getArgs();
            if(args == null){
                throw new RuntimeException("PayAwait注释的方法 必须有PayAwaitDTO参数");
            }
            PayAwaitDTO payAwaitDTO = null;
            for(Object arg : args){
                if(arg instanceof PayAwaitDTO){
                    payAwaitDTO = (PayAwaitDTO)arg;
                    break;
                }
            }
            if(payAwaitDTO == null){
                throw new RuntimeException("PayAwait注释的方法 必须有PayAwaitDTO参数");
            }
            if(payAwaitDTO.getPayDtoId() == null || payAwaitDTO.getPayDtoId().trim().equals("")){
                throw new RuntimeException("PayDTO.payDtoId不能为空");
            }
            if(payAwaitDTO.getMoney() == null){
                throw new RuntimeException("支付金额不能为空");
            }

            if(payAwaitDTO.getInvokeFlag() != null && payAwaitDTO.getInvokeFlag() == true){ // 反射调用
                return joinPoint.proceed();
            }

            // 测试环境添加测试,标记
            if(!FrameworkCommon.env.equals("pro")){
                payAwaitDTO.setPayRemark("测试," + payAwaitDTO.getPayRemark());
            }
            if(payAwaitDTO.getOverTimeSecond() == null){
                payAwaitDTO.setOverTimeSecond(30L * 60L);
            }

            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Class[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();

            ArrayList<PayArgsDto> payArgsDtos = new ArrayList<>();
            for(int i = 0 ; i < args.length ; i++){
                String paramClassName = parameterTypes[i].getName();
                Object arg = args[i];
                PayArgsDto payArgsDto = new PayArgsDto();
                payArgsDto.setClassName(paramClassName);
                payArgsDto.setObj(arg);
                payArgsDtos.add(payArgsDto);
            }


            PayInnerDto payInnerDto = new PayInnerDto();
            payInnerDto.setClassName(className);
            payInnerDto.setMethodName(methodName);
            payInnerDto.setArgs(payArgsDtos);

            payInnerDto.setUserContext(UserContextUtil.getContext());

            framworkPayInnerService.pay(payInnerDto);

            return null;
        }catch(Exception e){
            log.error("payAwait异常", e);
            throw e;
        }
    }
}
